#!/usr/bin/python
# -*- coding: utf-8 -*-

##
 # Copyright 2009 Caio Souza
 # This file is part of Rpyg.
 #
 # Rpyg is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation, either version 3 of the License, or
 # (at your option) any later version.
 #
 # Rpyg is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
 # along with Rpyg. If not, see <http://www.gnu.org/licenses/>.
 ##

from threading import Thread, RLock, Event

import pygame

from rpyg.Blitable import Blitable
from rpyg.Frame import Frame

class Image (Thread, Blitable):
    '''Uma imagem de um personagem ou objeto do jogo.
    
    Uma imagem contem diversos frames que são atualizados automaticamente
    por um thread da classe para simular movimentação.
    '''
    
    def __init__ (self, frames):
        '''Cria uma imagem a partir da lista de frames.'''
        
        Thread.__init__ (self)
        Blitable.__init__ (self)
        
        if isinstance (frames, Frame): frames = [frames]
        
        self._frames = list (frames)
        '''Lista de frames da imagem.'''
        
        self._first_surface = self._surface = self._frames[0].getSurface ()
        '''Primeira superfície da imagem.'''
        
        self._index = 0
        '''Índice do frame atual da imagem.'''
        
        self._lock = RLock  ()
        '''Cadeado para sincronia das lista de frames.'''
        
        self._event = Event ()
        '''Controla o estado da imagem.'''
        
        self._event.set ()
        self.setDaemon (True)
        if len (self._frames) > 1: self.start ()
        
    def _nextFrame (self):
        '''Atualiza o frame da imagem para o próximo da lista.'''
        
        self._event.wait ()
        with self._lock:
            self._index = (self._index + 1) % len (self._frames)
            self._surface = self._frames[self._index].getSurface ()
        
    def run (self):
        '''Roda a thread de atualização da imagem.'''
        
        while True:
            pygame.time.wait (self._frames[self._index].getTime ())
            self._nextFrame ()
    
    def pause (self):
        '''Pausa a atualização da imagem.'''
        
        self._event.clear ()
        
    def resume (self):
        '''Reinicia a atualização da imagem.'''
        
        self._event.set ()
        
    def stop (self):
        '''Para a atualização da imagem.'''
        
        self.pause ()
        with self._lock:
            self._index = 0
            self._surface = self._first_surface
            
    def __len__ (self):
        return len (self._frames)
